

#include <cassert>
#include "TCPMessageDevice.h"
IMPLEMENT_MESSAGE_ROUTER(TCPMessageRouter, "Free", "TCP Protocol based message router");

using namespace SAF;

bool TCPMessageRouter::Init(IKernel * kernel, IConfig * config)
{	
	void * defkey = NULL;
	PERFCOUNTER("TCPMessageDevice::Init");
	
	unsigned short port = (unsigned short)(atoi(config->GetValue("PORT")));
	if (port == 0)
	{
		kernel->OutputConsole("[TCP] Error: Port not defined.");
		return false;
	}

	this->m_hostKernel = kernel;
	this->m_defkey = defkey;	
	this->m_device = new MMONetwork::Server::MassiveConnectionDevice();
	if (this->m_device != NULL)
	{
		MMONetwork::Server::MassiveConnectionDevice::BuildParam param;

		param.MaxConnections	= atoi(config->GetValue("MAXCONNECTION"));
		param.MaxMessages		= atoi(config->GetValue("MESSAGESTACK"));
		param.RecvBufLength		= atoi(config->GetValue("RECVBUFLENGTH"));
		param.SendBufLength		= atoi(config->GetValue("SENDBUFLENGTH"));
		param.RecvTimeout		= atoi(config->GetValue("RECVTIMEOUT"));
		param.SendTimeout		= atoi(config->GetValue("SENDTIMEOUT"));		

		if (0 == param.MaxConnections)
		{				
			param.MaxConnections = 1024;
			kernel->OutputConsole("[TCP] Warnning: MAXCONNECTION not defined, set to default value %lu.", param.MaxConnections);
		}
		
		if (0 == param.MaxMessages)
		{				
			param.MaxMessages = param.MaxConnections * 2;
			kernel->OutputConsole("[TCP] Warnning: MESSAGESTACK not defined, set to default value %lu.", param.MaxMessages);
		}
		
		if (0 == param.RecvBufLength)
		{
			param.RecvBufLength = 65536;
			kernel->OutputConsole("[TCP] Warnning: RECVBUFLENGTH not defined, set to default value %lu.", param.RecvBufLength);
		}
		
		if (0 == param.SendBufLength)
		{
			param.SendBufLength = 65536;
			kernel->OutputConsole("[TCP] Warnning: RECVBUFLENGTH not defined, set to default value %lu.", param.SendBufLength);
		}

		if (0 == param.RecvTimeout)
		{
			if (strlen(config->GetValue("RECVTIMEOUT")) == 0)
			{
				kernel->OutputConsole("[TCP] Warnning: RECVTIMEOUT not defined, set to default value %lu.", param.RecvTimeout);
			}
		}
		
		if (0 == param.SendTimeout)
		{
			if (strlen(config->GetValue("SENDTIMEOUT")) == 0)
			{
				kernel->OutputConsole("[TCP] Warnning: SENDTIMEOUT not defined, set to default value %lu.", param.SendTimeout);
			}
		}

		if (this->m_device->Build(param))
		{
			if (this->m_device->CreateNode(0, 0, config->GetValue("IP"), port, defkey))
			{
				kernel->OutputConsole("[TCP] TCP message device listen at addr:%s:%d", config->GetValue("IP"), port);
				this->m_defkey = defkey;
				return true;
			}
			kernel->OutputConsole("[TCP] TCP message device listen failed.(addr:%s:%d)", config->GetValue("IP"), port);
			this->m_device->Destroy();
		}
		delete this->m_device;
		this->m_device = NULL;
	}
	return false;	
}

void TCPMessageRouter::Release()
{
	if (this->m_device != NULL)
	{
		this->m_device->Destroy();
		delete this->m_device;
		this->m_device = NULL;
	}
	return;
}


bool TCPMessageRouter::SendNetMessage(const SAF::IConnection * ptr_conn, const NetMessage& msg, const NetBuffer * buf, unsigned int count)
{
	PERFCOUNTER("TCPMessageDevice::SendNetMessage");

	MMONetwork::Server::ConnEntity		conn;
	MMONetwork::Server::MessageEntity	msge;

//	conn.node = id;
	conn.group = 0;		//unuse
	conn.routine = 0;	//unuse
	msge.seg = msg.catalog;
	msge.cmd = msg.command;
	msge.buf = 0;
	msge.len = 0;
	
	return (this->m_device->SendNetMessage(conn, msge, (MMONetwork::Server::AppendBuffer*)buf, count));	
}

bool TCPMessageRouter::RecvNetMessage(SAF::IConnection *& ptr_conn, NetPackage& pkg, unsigned int time)
{
	void ** lpkey = NULL;
	int id = 0;
	assert(this->m_device != NULL);

	PERFCOUNTER("TCPMessageDevice::RecvNetMessage");

	MMONetwork::Server::ConnEntity		conn;
	MMONetwork::Server::MessageEntity	msge;
	if (this->m_device->RecvNetMessage(conn, msge, lpkey))
	{
		PERFCOUNTER("TCPMessageDevice::RecvNetMessage::process");
		switch(msge.cmd)
		{
		case MMONetwork::Server::MassiveConnectionDevice::DEV_CONNECTION_CREATE:
			{
				static SAF::KERNEL::INTERNALCOMMAND::CONNECTIONJOIN_tag jointag;
				pkg.message.catalog = 0;
				pkg.message.command = SAF::KERNEL::INTERNALCOMMAND::CONNECTIONJOIN;
				jointag.connectionId = conn.node;
				in_addr addr;
				addr.s_addr = this->m_device->GetNodeIP(conn.group, conn.node);
				strcpy_s(jointag.connectionAddr, inet_ntoa(addr));
				jointag.connectionPort = 0;

				pkg.buffer.data = &jointag;
				pkg.buffer.size = sizeof(jointag);
				pkg.timestamp = time;
				id = 0;	*lpkey = this->m_defkey;
			}
			return true;
		case MMONetwork::Server::MassiveConnectionDevice::DEV_CONNECTION_DESTROY:
			{
				static SAF::KERNEL::INTERNALCOMMAND::CONNECTIONHANDLE_tag handletag;
				pkg.message.catalog = 0;
				pkg.message.command = SAF::KERNEL::INTERNALCOMMAND::CONNECTIONDROP;
				//handletag.connectionHandle = (IConnection *)(*lpkey);
				pkg.buffer.data = &handletag;
				pkg.buffer.size = sizeof(handletag);
				pkg.timestamp = time;
//				id = 0;	*lpkey = this->m_defkey;
			}
			return true;
		case MMONetwork::Server::MassiveConnectionDevice::DEV_CONNECTION_BROKEN:
			{
				static SAF::KERNEL::INTERNALCOMMAND::CONNECTIONHANDLE_tag handletag;
				pkg.message.catalog = 0;
				pkg.message.command = SAF::KERNEL::INTERNALCOMMAND::CONNECTIONBROKEN;				
//				handletag.connectionHandle = (IConnection *)(*lpkey);
				pkg.buffer.data = &handletag;
				pkg.buffer.size = sizeof(handletag);
				pkg.timestamp = time;
//				id = 0;	*lpkey = this->m_defkey;
			}
			return true;	
		default:
			{
				id = conn.node;
				pkg.message.catalog = msge.seg;
				pkg.message.command = msge.cmd;
				pkg.buffer.data		= msge.buf;
				pkg.buffer.size		= msge.len;			
				pkg.timestamp = time;			
			}
			return true;
		}
	}
	return false;
}

//bool TCPMessageRouter::BindConnection(unsigned long id, void * key)
//{
//	PERFCOUNTER("TCPMessageDevice::BindConnection");
//
//	if (id != 0)
//	{
//		return this->m_device->BindNodeKey(0, id, key);	
//	}
//	else
//	{
//		this->m_defkey = key;
//		return true;
//	}	
//}

bool TCPMessageRouter::DropConnection(const SAF::IConnection * conn)
{
	PERFCOUNTER("TCPMessageDevice::DropConnection");

	//this->m_device->RemoveNode(0, id);
	return true;
}
